﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using System.Threading;
using Mbs;
using Mbs.Messaging;

namespace MBTest
{
    [TestFixture]
    public class MessageRouterTest
    {
        [Test]
        public void SimpleTest()
        {
            var mre = new ManualResetEvent(false);
            MB.Subscribe<int>((s,msg) =>
            {
                if (msg == -1)
                {
                    MB.Remove<int>();
                    mre.Set();
                }
                Console.WriteLine(msg.ToString());
            });

            for (int i = 0; i < 100; i++)
            {
                MB.Publish(i);
            }

            MB.Publish(-1);
            mre.WaitOne();
        }

        [Test]
        public void TopicTest()
        {
            const string topic = "TopicTest";
            var mre = new ManualResetEvent(false);

            MB.Subscribe<int>(topic,(s,msg )=>
            {
                if (msg.Message == -1)
                {
                    MB.Remove<int>(topic);
                    mre.Set();
                }
                Console.WriteLine(msg.ToString() + " for " + topic + "!");
                
            });

            for (int i = 0; i < 100; i++)
            {
                MB.Publish(topic, i);
            }

            MB.Publish(topic, -1);
            mre.WaitOne();

        }

        [Test]
        public void PreFilterTest()
        {
            const string topic = "PreFilterTest";
            var mre = new ManualResetEvent(false);

            MB.Subscribe<int>(topic, (s,msg) =>
            {
                //Assert.IsTrue(msg % 2 == 0);
                Console.WriteLine(msg.ToString() + " for " + topic + "!");
            });

            MB.SubscribePreFilter<int>(topic,(s, p) =>
            {
                p.Canceled = p.Message.Message % 2 != 0;
                if (p.Message.Message == -1)
                {
                    MB.Remove<int>(topic);

                    mre.Set();
                }
            });
            for (int i = 0; i < 100; i++)
            {
                MB.Publish(topic, i);
            }

            MB.Publish(topic, -1);
            mre.WaitOne();
        }

        [Test]
        public void FilterTest()
        {
            const string topic = "FilterTest";
            var mre = new ManualResetEvent(false);

            var noRunSubscriber = new FilterObject(topic);
            var subscriber = new NoFilterObject(topic);
            var subscriber2 = new NoFilterObject2(topic);
            var subscriber3 = new NoFilterObject3(topic);
            var subscriber4 = new NoFilterObject4(topic);
            var subscriber5 = new NoFilterObject5(topic);

            MB.SubscribePreFilter<int>(topic,(s, p) =>
            {
                
                if(p.Canceled = p.Message.Message == -1)
                    mre.Set();
            });

            MB.SubscribeFilter<int>(topic, (s,p) =>
            {
                p.Ignored = p.Receiver == null
                    || (p.Receiver != null && p.Receiver is IFilterObject);
            });

            for (int i = 0; i < 100; i++)
            {
                MB.Publish(topic, i);
            }


            MB.Publish(topic, -1);
            mre.WaitOne();
        }


        class FilterObject : IFilterObject
        {
            public FilterObject(string topic)
            {
                MB.Subscribe<int>(topic, (s, msg) =>
                {
                    Console.WriteLine("No executed in FilterObject");
                });
            }
        }

        interface IFilterObject
        {
        }
        class NoFilterObject
        {
            private string topic;
            private void Act(object sender,Topic<int> msg)
            {
                if (msg.Message % 2 != 0)
                    Console.WriteLine("NoFilterObject: " + msg.ToString() + " for " + topic + "!");
            }

            public NoFilterObject(string topic)
            {
                this.topic = topic;

                MB.Subscribe<int>(topic, Act);
            }
        }

        class NoFilterObject2
        {
            private string topic;
            private void Act(object sender, Topic<int> msg)
            {
                if (msg.Message % 2 == 0)
                    Console.WriteLine("NoFilterObject2: " + msg.ToString() + " for " + topic + "!");
            }

            public NoFilterObject2(string topic)
            {
                this.topic = topic;
                MB.Subscribe<int>(topic, Act);
            }
        }

        class NoFilterObject3
        {
            private string topic;

            public NoFilterObject3(string topic)
            {
                this.topic = topic;
                MB.Subscribe<int>(topic,(s, msg) => Console.WriteLine("No executed in NoFilterObject3!"));
            }
        }

        class NoFilterObject4
        {
            private string topic;

            public NoFilterObject4(string topic)
            {
                this.topic = topic;
                ObserverHandler<Topic<int>> act = (s,msg) =>
                {
                    Console.WriteLine("No executed in NoFilterObject4!");
                };

                MB.Subscribe<int>(topic, act);
            }
        }

        class NoFilterObject5
        {
            private string topic;

            public NoFilterObject5(string topic)
            {
                this.topic = topic;
                MB.Subscribe<int>(topic,NoFilterObject5_Receive);
            }

            void NoFilterObject5_Receive(object sender, Topic<int> msg)
            {
                if (msg.Message % 5 == 0)
                    Console.WriteLine("NoFilterObject5: " + msg.Message.ToString() + " for " + topic + "!");
            }
        }

        public static IMessageBus MB { get; protected set; }
        [SetUp]
        public virtual void Setup()
        {
            MB = new MessageBus();
        }

        [TearDown]
        public void TearDown()
        {
            MB.Dispose();
        }
    }


    //[TestFixture]
    //public class MessageRouter2Test
    //{
    //    [Test]
    //    public void SimpleTest()
    //    {
    //        var mre = new ManualResetEvent(false);
    //        MB.Subscribe<int>( (s, msg) =>
    //        {
    //            if (msg == -1)
    //            {
    //                MB.Remove<int>();
    //                mre.Set();
    //            }
    //            Console.WriteLine(msg.ToString());
    //        });

    //        for (int i = 0; i < 100; i++)
    //        {
    //            MB.Publish(i);
    //        }

    //        MB.Publish(-1);
    //        mre.WaitOne();
    //    }

    //    [Test]
    //    public void TopicTest()
    //    {
    //        const string topic = "TopicTest";
    //        var mre = new ManualResetEvent(false);

    //        MB.Subscribe<int>(topic, (s, msg) =>
    //        {
    //            if (msg.Message == -1)
    //            {
    //                MB.Remove<int>(topic);
    //                mre.Set();
    //            }
    //            Console.WriteLine(msg.ToString() + " for " + topic + "!");

    //        });

    //        for (int i = 0; i < 100; i++)
    //        {
    //            MB.Publish(topic, i);
    //        }

    //        MB.Publish(topic, -1);
    //        mre.WaitOne();

    //    }

    //    [Test]
    //    public void PreFilterTest()
    //    {
    //        const string topic = "PreFilterTest";
    //        var mre = new ManualResetEvent(false);

    //        MB.Subject<int>(topic).Observers += (s, msg) =>
    //        {
    //            Console.WriteLine(msg.ToString() + " for " + topic + "!");
    //        };

    //        MB.Subject<int>(topic).PreFilters += (s, m) =>
    //        {
    //            m.Canceled = m.Message.Message % 2 != 0;
    //            if (m.Message.Message == -1)
    //            {
    //                MB.Remove<int>(topic);
    //                mre.Set();
    //            }
    //        };
    //        for (int i = 0; i < 100; i++)
    //        {
    //            MB.Publish(topic, i);
    //        }

    //        MB.Publish(topic, -1);
    //        mre.WaitOne();
    //    }

    //    [Test]
    //    public void FilterTest()
    //    {
    //        const string topic = "FilterTest";
    //        var mre = new ManualResetEvent(false);

    //        var noRunSubscriber = new FilterObject(topic);
    //        var subscriber = new NoFilterObject(topic);
    //        var subscriber2 = new NoFilterObject2(topic);
    //        var subscriber3 = new NoFilterObject3(topic);
    //        var subscriber4 = new NoFilterObject4(topic);
    //        var subscriber5 = new NoFilterObject5(topic);

    //        MB.Subject<int>(topic).PreFilters += (s, m) =>
    //        {

    //            if (m.Canceled = m.Message.Message == -1)
    //                mre.Set();
    //        };

    //        MB.Subject<int>(topic).Filters += (s, m) =>
    //        {
    //            m.Ignored = m.Receiver == null
    //                || (m.Receiver != null && m.Receiver is IFilterObject);
    //        };

    //        for (int i = 0; i < 100; i++)
    //        {
    //            MB.Publish(topic, i);
    //        }


    //        MB.Publish(topic, -1);
    //        mre.WaitOne();
    //    }


    //    class FilterObject : IFilterObject
    //    {
    //        public FilterObject(string topic)
    //        {
    //            MB.Subscribe<int>(topic, (s, msg) =>
    //            {
    //                Console.WriteLine("No executed in FilterObject");
    //            });
    //        }
    //    }

    //    interface IFilterObject
    //    {
    //    }
    //    class NoFilterObject
    //    {
    //        private string topic;
    //        private void Act(object sender, Topic<int> msg)
    //        {
    //            if (msg.Message % 2 != 0)
    //                Console.WriteLine("NoFilterObject: " + msg.ToString() + " for " + topic + "!");
    //        }

    //        public NoFilterObject(string topic)
    //        {
    //            this.topic = topic;

    //            MB.Subscribe<int>(topic, Act);
    //        }
    //    }

    //    class NoFilterObject2
    //    {
    //        private string topic;
    //        private void Act(object sender, Topic<int> msg)
    //        {
    //            if (msg.Message % 2 == 0)
    //                Console.WriteLine("NoFilterObject2: " + msg.ToString() + " for " + topic + "!");
    //        }

    //        public NoFilterObject2(string topic)
    //        {
    //            this.topic = topic;
    //            MB.Subscribe<int>(topic, Act);
    //        }
    //    }

    //    class NoFilterObject3
    //    {
    //        private string topic;

    //        public NoFilterObject3(string topic)
    //        {
    //            this.topic = topic;
    //            MB.Subscribe<int>(topic, (s, msg) => Console.WriteLine("No executed in NoFilterObject3!"));
    //        }
    //    }

    //    class NoFilterObject4
    //    {
    //        private string topic;

    //        public NoFilterObject4(string topic)
    //        {
    //            this.topic = topic;
    //            ObserverHandler<Topic<int>> act = (s, msg) =>
    //            {
    //                Console.WriteLine("No executed in NoFilterObject4!");
    //            };

    //            MB.Subscribe<int>(topic, act);
    //        }
    //    }

    //    class NoFilterObject5
    //    {
    //        private string topic;

    //        public NoFilterObject5(string topic)
    //        {
    //            this.topic = topic;
    //            MB.Subscribe<int>(topic, NoFilterObject5_Receive);
    //        }

    //        void NoFilterObject5_Receive(object sender, Topic<int> msg)
    //        {
    //            if (msg.Message % 5 == 0)
    //                Console.WriteLine("NoFilterObject5: " + msg.Message.ToString() + " for " + topic + "!");
    //        }
    //    }

    //    public static IMessageBus MB { get; protected set; }
    //    [SetUp]
    //    public virtual void Setup()
    //    {
    //        MB = new MessageBus();
    //    }

    //    [TearDown]
    //    public void TearDown()
    //    {
    //        MB.Dispose();
    //    }
    //}

}
